﻿using CgdataBase;
using FilterCopyer.Views;
using Microsoft.Xaml.Behaviors;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using static FilterCopyer.Properties.Resources;
using FolderBrowserDialog = System.Windows.Forms.FolderBrowserDialog;
using MessageBox = FilterCopyer.Views.MessageBox;

namespace FilterCopyer.ViewModels
{
    public class MainWindowViewModel : BindableBase, IBusyScope
    {
        private readonly MainWindow _win;
        private Prism.Events.IEventAggregator Aggregator => EventHelper.Aggregator;
        private DataHelper DbHelper => DataHelper.Instance;
        private AppSettings Settings => AppSettings.Instance;
        public int FontSize => Settings.FontSize;
        public string FontName => Settings.FontName;
        public string Title { get; set; }

        public bool IsBusy { get; set; }
        public string BusyContent { get; set; }
        public ConcurrentStack<bool> BusyStack { get; set; } = new ConcurrentStack<bool>();
        public bool Topmost { get; set; }

        public string IgnoreFolder { get; set; }
        public int IgnoreFolderFocused { get; set; }

        public string IgnoreFile { get; set; }
        public int IgnoreFileFocused { get; set; }

        public string RecursiveIgnoreFolder { get; set; }
        public int RecursiveIgnoreFolderFocused { get; set; }

        public string RecursiveIgnoreFile { get; set; }
        public int RecursiveIgnoreFileFocused { get; set; }

        public string FullCopyFolder { get; set; }

        public DelegateCommand AboutCommand { get; }
        public DelegateCommand SettingsCommand { get; }
        public DelegateCommand<CancelEventArgs> ClosingCommand { get; private set; }
        public DelegateCommand<DragEventArgs> DropCommand { get; private set; }

        public MainWindowViewModel(MainWindow win)
        {
            _win = win;
            Title = ApplicationName;

            ObjectHelper.DeepCopy(Settings, this);

            AboutCommand = new DelegateCommand(OnAbout);
            SettingsCommand = new DelegateCommand(OnSettings);
            ClosingCommand = new DelegateCommand<CancelEventArgs>(OnClosing);
            DropCommand = new DelegateCommand<DragEventArgs>(OnDrop);
            Aggregator.GetEvent<ShowWindowEvent>().Subscribe(OnShowWindow, ThreadOption.UIThread);
        }

        private async void OnDrop(DragEventArgs e)
        {
            try
            {
                var fileNames = (string[])e.Data.GetData(DataFormats.FileDrop, false);

                if (fileNames.IsNullOrEmpty())
                    return;

                var dialog = new FolderBrowserDialog();
                if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    var targetPath = dialog.SelectedPath;

                    CancellationToken token = new CancellationToken();
                    var info = new ConfigInfo();
                    info.IgnoreFolder = IgnoreFolder.StringSplit(new string[] { "\r\n", "\n" });
                    info.IgnoreFile = IgnoreFile.StringSplit(new string[] { "\r\n", "\n" });
                    info.RecursiveIgnoreFolder = RecursiveIgnoreFolder.StringSplit(new string[] { "\r\n", "\n" });
                    info.RecursiveIgnoreFile = RecursiveIgnoreFile.StringSplit(new string[] { "\r\n", "\n" });
                    info.FullCopyFolder = FullCopyFolder.StringSplit(new string[] { "\r\n", "\n" });

                    using (var scope = new BusyScope(this))
                    {
                        await Task.Run(() =>
                        {
                            foreach (var dirName in fileNames)
                            {
                                if (Directory.Exists(dirName))
                                {
                                    CopyFolder(new DirectoryInfo(dirName),
                                        new DirectoryInfo(Path.Combine(targetPath, Path.GetFileName(dirName))),
                                        info, token);
                                }
                            }
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                MessageBox.Show("操作异常：" + ex.Message);
            }
        }

        private static void CopyFolder(DirectoryInfo source, DirectoryInfo target, ConfigInfo info, CancellationToken token)
        {
            Directory.CreateDirectory(target.FullName);
            foreach (FileInfo file in source.GetFiles())
            {
                token.ThrowIfCancellationRequested();

                if (info.IgnoreFile?.Contains(file.Name) == true || info.RecursiveIgnoreFile?.Contains(file.Name) == true)
                {
                    //跳过
                }
                else
                {
                    file.CopyTo(Path.Combine(target.FullName, file.Name), true);
                }
            }
            foreach (DirectoryInfo sourceSubDir in source.GetDirectories())
            {
                token.ThrowIfCancellationRequested();

                if (info.IgnoreFolder?.Contains(sourceSubDir.Name) == true
                    || info.RecursiveIgnoreFolder?.Contains(sourceSubDir.Name) == true)
                {
                    //跳过
                }
                else
                {
                    DirectoryInfo targetSubDir = target.CreateSubdirectory(sourceSubDir.Name);
                    if (info.FullCopyFolder?.Contains(sourceSubDir.Name) == true)
                    {
                        FileSystemHelper.CopyFolder(sourceSubDir.FullName, targetSubDir.FullName, token);
                    }
                    else
                    {
                        var info2 = new ConfigInfo();
                        info2.RecursiveIgnoreFile = info.RecursiveIgnoreFile;
                        info2.RecursiveIgnoreFolder = info.RecursiveIgnoreFolder;
                        info2.FullCopyFolder = info.FullCopyFolder;

                        CopyFolder(sourceSubDir, targetSubDir, info2, token);
                    }
                }
            }
        }

        private void OnClosing(CancelEventArgs e)
        {
            ObjectHelper.DeepCopy(this, Settings);
        }

        private void OnAbout()
        {
            new WinAbout() { Owner = App.GetActiveWindow() }.ShowDialog();
        }

        private void OnSettings()
        {
            try
            {
                var win = new WinSettings { Owner = App.GetActiveWindow() };
                if (win.ShowDialog() == true)
                {
                    RaisePropertyChanged(nameof(FontName));
                    RaisePropertyChanged(nameof(FontSize));
                    App.InitializeDatabase();
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                MessageBox.Show("操作异常：" + ex.Message);
            }
        }

        private void OnShowWindow()
        {
            _win.Show();
            if (_win.WindowState == WindowState.Minimized)
            {
                _win.WindowState = WindowState.Maximized;
            }
            _win.Activate();
        }
    }

    public class ConfigInfo
    {
        public string[] IgnoreFolder { get; set; }
        public string[] IgnoreFile { get; set; }
        public string[] RecursiveIgnoreFolder { get; set; }
        public string[] RecursiveIgnoreFile { get; set; }
        public string[] FullCopyFolder { get; set; }
    }
}